// @nolint
// This file creates the internal module & binding loaders used by built-in
// modules. In contrast, user land modules are loaded using
// lib/internal/modules/cjs/loader.js (CommonJS Modules) or
// lib/internal/modules/esm/* (ES Modules).
//
// This file is compiled and run by node.cc before bootstrap/node.js
// was called, therefore the loaders are bootstrapped before we start to
// actually bootstrap Node.js. It creates the following objects:
//
// C++ binding loaders:
// - process.binding(): the legacy C++ binding loader, accessible from user land
//   because it is an object attached to the global process object.
//   These C++ bindings are created using NODE_BUILTIN_MODULE_CONTEXT_AWARE()
//   and have their nm_flags set to NM_F_BUILTIN. We do not make any guarantees
//   about the stability of these bindings, but still have to take care of
//   compatibility issues caused by them from time to time.
// - process._linkedBinding(): intended to be used by embedders to add
//   additional C++ bindings in their applications. These C++ bindings
//   can be created using NODE_MODULE_CONTEXT_AWARE_CPP() with the flag
//   NM_F_LINKED.
// - internalBinding(): the private internal C++ binding loader, inaccessible
//   from user land unless through `require('internal/test/binding')`.
//   These C++ bindings are created using NODE_MODULE_CONTEXT_AWARE_INTERNAL()
//   and have their nm_flags set to NM_F_INTERNAL.
//
// Internal JavaScript module loader:
// - NativeModule: a minimal module system used to load the JavaScript core
//   modules found in lib/**/*.js and deps/**/*.js. All core modules are
//   compiled into the node binary via node_javascript.cc generated by js2c.py,
//   so they can be loaded faster without the cost of I/O. This class makes the
//   lib/internal/*, deps/internal/* modules and internalBinding() available by
//   default to core modules, and lets the core modules require itself via
//   require('internal/bootstrap/loaders') even when this file is not written in
//   CommonJS style.
//
// Other objects:
// - process.moduleLoadList: an array recording the bindings and the modules
//   loaded in the process and the order in which they are loaded.
'use strict'; // This file is compiled as if it's wrapped in a function with arguments
// passed by node::RunBootstrapping()

/* global process, getLinkedBinding, getInternalBinding, primordials */

function _createForOfIteratorHelper(o, allowArrayLike) { var it = typeof Symbol !== "undefined" && o[Symbol.iterator] || o["@@iterator"]; if (!it) { if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === "number") { if (it) o = it; var i = 0; var F = function F() {}; return { s: F, n: function n() { if (i >= o.length) return { done: true }; return { done: false, value: o[i++] }; }, e: function e(_e) { throw _e; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var normalCompletion = true, didErr = false, err; return { s: function s() { it = it.call(o); }, n: function n() { var step = it.next(); normalCompletion = step.done; return step; }, e: function e(_e2) { didErr = true; err = _e2; }, f: function f() { try { if (!normalCompletion && it["return"] != null) it["return"](); } finally { if (didErr) throw err; } } }; }

function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }

function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) { arr2[i] = arr[i]; } return arr2; }

function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }

function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }

function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }

function _typeof(obj) { "@babel/helpers - typeof"; if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); }

var _primordials = primordials,
    ArrayPrototypeMap = _primordials.ArrayPrototypeMap,
    ArrayPrototypePush = _primordials.ArrayPrototypePush,
    ArrayPrototypeSlice = _primordials.ArrayPrototypeSlice,
    Error = _primordials.Error,
    ObjectCreate = _primordials.ObjectCreate,
    ObjectDefineProperty = _primordials.ObjectDefineProperty,
    ObjectKeys = _primordials.ObjectKeys,
    ObjectPrototypeHasOwnProperty = _primordials.ObjectPrototypeHasOwnProperty,
    ReflectGet = _primordials.ReflectGet,
    SafeMap = _primordials.SafeMap,
    SafeSet = _primordials.SafeSet,
    String = _primordials.String,
    StringPrototypeStartsWith = _primordials.StringPrototypeStartsWith,
    _TypeError = _primordials.TypeError; // Set up process.moduleLoadList.

var moduleLoadList = [];
ObjectDefineProperty(process, 'moduleLoadList', {
  value: moduleLoadList,
  configurable: true,
  enumerable: true,
  writable: false
}); // internalBindingAllowlist contains the name of internalBinding modules
// that are allowed for access via process.binding()... This is used
// to provide a transition path for modules that are being moved over to
// internalBinding.

var internalBindingAllowlist = new SafeSet(['async_wrap', 'buffer', 'cares_wrap', 'config', 'constants', 'contextify', 'crypto', 'fs', 'fs_event_wrap', 'http_parser', 'icu', 'inspector', 'js_stream', 'natives', 'os', 'pipe_wrap', 'process_wrap', 'signal_wrap', 'spawn_sync', 'stream_wrap', 'tcp_wrap', 'tls_wrap', 'tty_wrap', 'udp_wrap', 'url', 'util', 'uv', 'v8', 'zlib']);
var runtimeDeprecatedList = new SafeSet(['async_wrap', 'crypto', 'http_parser', 'signal_wrap', 'url', 'v8']);
var legacyWrapperList = new SafeSet(['util']); // Set up process.binding() and process._linkedBinding().

{
  var bindingObj = ObjectCreate(null);

  process.binding = function binding(module) {
    module = String(module); // Deprecated specific process.binding() modules, but not all, allow
    // selective fallback to internalBinding for the deprecated ones.

    if (internalBindingAllowlist.has(module)) {
      if (runtimeDeprecatedList.has(module)) {
        runtimeDeprecatedList["delete"](module);
        process.emitWarning("Access to process.binding('".concat(module, "') is deprecated."), 'DeprecationWarning', 'DEP0111');
      }

      if (legacyWrapperList.has(module)) {
        return nativeModuleRequire('internal/legacy/processbinding')[module]();
      }

      return internalBinding(module);
    } // eslint-disable-next-line no-restricted-syntax


    throw new Error("No such module: ".concat(module));
  };

  process._linkedBinding = function _linkedBinding(module) {
    module = String(module);
    var mod = bindingObj[module];
    if (_typeof(mod) !== 'object') mod = bindingObj[module] = getLinkedBinding(module);
    return mod;
  };
} // Set up internalBinding() in the closure.

/**
 * @type {InternalBinding}
 */

// var internalBinding;
// {
//   var _bindingObj = ObjectCreate(null); // eslint-disable-next-line no-global-assign


//   internalBinding = function internalBinding(module) {
//     var mod = _bindingObj[module];

//     if (_typeof(mod) !== 'object') {
//       mod = _bindingObj[module] = getInternalBinding(module);
//       ArrayPrototypePush(moduleLoadList, "Internal Binding ".concat(module));
//     }

//     return mod;
//   };
// }
var loaderId = 'internal/bootstrap/loaders';

var _internalBinding = internalBinding('native_module'),
    moduleIds = _internalBinding.moduleIds,
    compileFunction = _internalBinding.compileFunction;

var getOwn = function getOwn(target, property, receiver) {
  return ObjectPrototypeHasOwnProperty(target, property) ? ReflectGet(target, property, receiver) : undefined;
};
/**
 * An internal abstraction for the built-in JavaScript modules of Node.js.
 * Be careful not to expose this to user land unless --expose-internals is
 * used, in which case there is no compatibility guarantee about this class.
 */


var NativeModule = /*#__PURE__*/function () {
  /**
   * A map from the module IDs to the module instances.
   * @type {Map<string, NativeModule>}
  */
  function NativeModule(id) {
    _classCallCheck(this, NativeModule);

    this.filename = "".concat(id, ".js");
    this.id = id;
    this.canBeRequiredByUsers = !StringPrototypeStartsWith(id, 'internal/'); // The CJS exports object of the module.

    this.exports = {}; // States used to work around circular dependencies.

    this.loaded = false;
    this.loading = false; // The following properties are used by the ESM implementation and only
    // initialized when the native module is loaded by users.

    /**
     * The C++ ModuleWrap binding used to interface with the ESM implementation.
     * @type {ModuleWrap|undefined}
     */

    this.module = undefined;
    /**
     * Exported names for the ESM imports.
     * @type {string[]|undefined}
     */

    this.exportKeys = undefined;
  } // To be called during pre-execution when --expose-internals is on.
  // Enables the user-land module loader to access internal modules.


  _createClass(NativeModule, [{
    key: "compileForPublicLoader",
    value: // Used by user-land module loaders to compile and load builtins.
    function compileForPublicLoader() {
      if (!this.canBeRequiredByUsers) {
        // No code because this is an assertion against bugs
        // eslint-disable-next-line no-restricted-syntax
        throw new Error("Should not compile ".concat(this.id, " for public use"));
      }

      this.compileForInternalLoader();

      if (!this.exportKeys) {
        // When using --expose-internals, we do not want to reflect the named
        // exports from core modules as this can trigger unnecessary getters.
        var internal = StringPrototypeStartsWith(this.id, 'internal/');
        this.exportKeys = internal ? [] : ObjectKeys(this.exports);
      }

      this.getESMFacade();
      this.syncExports();
      return this.exports;
    }
  }, {
    key: "getESMFacade",
    value: function getESMFacade() {
      if (this.module) return this.module;

      var _internalBinding2 = internalBinding('module_wrap'),
          ModuleWrap = _internalBinding2.ModuleWrap;

      var url = "node:".concat(this.id);
      var nativeModule = this;
      var exportsKeys = ArrayPrototypeSlice(this.exportKeys);
      ArrayPrototypePush(exportsKeys, 'default');
      this.module = new ModuleWrap(url, undefined, exportsKeys, function () {
        nativeModule.syncExports();
        this.setExport('default', nativeModule.exports);
      }); // Ensure immediate sync execution to capture exports now

      this.module.instantiate();
      this.module.evaluate(-1, false);
      return this.module;
    } // Provide named exports for all builtin libraries so that the libraries
    // may be imported in a nicer way for ESM users. The default export is left
    // as the entire namespace (module.exports) and updates when this function is
    // called so that APMs and other behavior are supported.

  }, {
    key: "syncExports",
    value: function syncExports() {
      var names = this.exportKeys;

      if (this.module) {
        for (var i = 0; i < names.length; i++) {
          var exportName = names[i];
          if (exportName === 'default') continue;
          this.module.setExport(exportName, getOwn(this.exports, exportName, this.exports));
        }
      }
    }
  }, {
    key: "compileForInternalLoader",
    value: function compileForInternalLoader() {
      if (this.loaded || this.loading) {
        return this.exports;
      }

      var id = this.id;
      this.loading = true;

      try {
        var requireFn = StringPrototypeStartsWith(this.id, 'internal/deps/') ? requireWithFallbackInDeps : nativeModuleRequire;
        var fn = compileFunction(id);
        fn(this.exports, requireFn, this, process, internalBinding, primordials);
        this.loaded = true;
      } finally {
        this.loading = false;
      }

      ArrayPrototypePush(moduleLoadList, "NativeModule ".concat(id));
      return this.exports;
    }
  }], [{
    key: "exposeInternals",
    value: function exposeInternals() {
      var _iterator = _createForOfIteratorHelper(NativeModule.map),
          _step;

      try {
        for (_iterator.s(); !(_step = _iterator.n()).done;) {
          var _step$value = _step.value,
              id = _step$value[0],
              mod = _step$value[1];

          // Do not expose this to user land even with --expose-internals.
          if (id !== loaderId) {
            mod.canBeRequiredByUsers = true;
          }
        }
      } catch (err) {
        _iterator.e(err);
      } finally {
        _iterator.f();
      }
    }
  }, {
    key: "exists",
    value: function exists(id) {
      return NativeModule.map.has(id);
    }
  }, {
    key: "canBeRequiredByUsers",
    value: function canBeRequiredByUsers(id) {
      var mod = NativeModule.map.get(id);
      return mod && mod.canBeRequiredByUsers;
    }
  }]);

  return NativeModule;
}(); // Think of this as module.exports in this file even though it is not
// written in CommonJS style.


_defineProperty(NativeModule, "map", new SafeMap(ArrayPrototypeMap(moduleIds, function (id) {
  return [id, new NativeModule(id)];
})));

var loaderExports = {
  internalBinding: internalBinding,
  NativeModule: NativeModule,
  require: nativeModuleRequire
};

function nativeModuleRequire(id) {
  if (id === loaderId) {
    return loaderExports;
  }

  var mod = NativeModule.map.get(id); // Can't load the internal errors module from here, have to use a raw error.
  // eslint-disable-next-line no-restricted-syntax

  if (!mod) throw new _TypeError("Missing internal module '".concat(id, "'"));
  return mod.compileForInternalLoader();
} // Allow internal modules from dependencies to require
// other modules from dependencies by providing fallbacks.


function requireWithFallbackInDeps(request) {
  if (!NativeModule.map.has(request)) {
    request = "internal/deps/".concat(request);
  }

  return nativeModuleRequire(request);
} // Pass the exports back to C++ land for C++ internals to use.
// return loaderExports;
